from django_redis import get_redis_connection
from redis import StrictRedis
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import Serializer

from oauth.models import OAuthQQUser
from oauth.utils import check_openid
from users.models import User


class QQUserSerializer(Serializer):
    """QQ登录创建用户序列化器"""
    openid = serializers.CharField(label='openid', write_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$', write_only=True)
    password = serializers.CharField(label='密码', min_length=8, max_length=20, write_only=True)
    sms_code = serializers.CharField(label="验证码", max_length=6, write_only=True)

    # 1. 获取请求参数: mobile, password, sms_code, openid
    def validate(self, attrs):
        mobile = attrs.get('mobile')
        sms_code = attrs.get('sms_code')
        password = attrs.get('password')
        # 2. 校验openid是否合法
        # 获取openid, 校验openid是否有效
        encrypted_openid = attrs['openid']
        openid = check_openid(encrypted_openid)
        if not openid:
            raise serializers.ValidationError({'message': '无效openid'})
        # 修改字典中openid的值， 以便保存正确的openid到映射表
        attrs['openid'] = openid
        # 3. 校验短信验证码是否正确
        # 获取StrictRedis对象
        strict_redis = get_redis_connection('sms_codes')  # type: StrictRedis
        # 先查询ｒｅｄｉｓ中是否存在,如果不存在则说明验证码过期
        real_sms_code = strict_redis.get('sms_%s' % mobile)
        # print("real_sms_code", real_sms_code)
        if real_sms_code is None:
            raise ValidationError({'message': '验证码已过期'})
        # 获取用户输入的验证码，校验与生成的是否一致，存在ｒｅｄｉｓ中是字节串，需要解码
        if sms_code != real_sms_code.decode():
            raise ValidationError({'message': '验证码不正确'})
        # 4. 判断要绑定的用户是否存在
        # 	- 用户不存在，则以手机号作为用户名，创建美多用户
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果不存在手机号作为用户名，创建美多用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
            # 	- 用户存在，判断密码是否正确

        else:
            if not user.check_password(password):
                raise ValidationError({'message': '密码不正确'})
        # 给attrs字典添加user用户对象, 以便在create方法中使用
        attrs['user'] = user
        return attrs

    def create(self, validated_data):
        # create() : 绑定逻辑实现
        # 5. 绑定openid和美多用户（往映射表添加一条数据）
        openid = validated_data.get('openid')
        print(openid)
        user = validated_data.get('user')
        OAuthQQUser.objects.create(openid=openid, user=user)
        return user  # 注意返回的数据，OAuthQQUser只是个映射表，没实际我们美多数据
